package controller

import (
	"errors"
	"os"

	"jtdevice/pkg/ctx"

	"github.com/dontls/xproto"
	"github.com/gin-gonic/gin"
)

type formParam struct {
	deviceID string
}

func checkParam(c *gin.Context, param interface{}) (*formParam, error) {
	dvr := &formParam{}
	dvr.deviceID = c.Query("deviceNo")
	if dvr.deviceID == "" {
		return nil, errors.New("invalid deviceID")
	}
	if param == nil {
		return dvr, nil
	}
	return dvr, c.ShouldBind(&param)
}

type Request struct {
}

// ControlHandler 控制
func (Request) ControlHandler(c *gin.Context) {
	var param xproto.Control
	i, err := checkParam(c, &param.Data)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqControl, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrQuery 查询
func (Request) QueryHandler(c *gin.Context) {
	var param xproto.Query
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp []xproto.File
	if err := xproto.SyncSend(xproto.ReqQuery, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrParameters 参数管理 获取/设置
func (Request) ParametersHandler(c *gin.Context) {
	var param interface{}
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqParameters, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// UserHandler自定义
func (Request) UserHandler(c *gin.Context) {
	var param xproto.User
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqUser, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrLiveStream 实时视频请求
// return url 直接打开播放
func (Request) LiveStreamHandler(c *gin.Context) {
	var param xproto.LiveStream
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	// s := serve.GetServeOfType(model.ServeTypeStream)
	// if s == nil {
	// 	ctx.JSONWriteError(errors.New("no live stream serve can use"), c)
	// 	return
	// }
	// param.Server = fmt.Sprintf("%s:%d", s.Address, s.AccessPort)
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqLiveStream, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	// v, ok := resp.(map[string]interface{})
	// if ok {
	// 	v["url"] = fmt.Sprintf("http://%s:%d/live", s.Address, s.Port)
	// }
	ctx.JSONWriteData(resp, c)
}

// VoiceHandler 语音
func (Request) VoiceHandler(c *gin.Context) {
	var param xproto.Voice
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqVoice, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// PlaybackHandler 录像回放
func (Request) PlaybackHandler(c *gin.Context) {
	var param xproto.Playback
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqPlayback, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrSerialTransparent 串口透传设置
func (Request) SerialTransparentHandler(c *gin.Context) {
	var param xproto.SerialTransparent
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqSerialTransparent, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrSerialTransfer 串口透传数据
func (Request) SerialTransferHandler(c *gin.Context) {
	session := c.Query("session")
	if session == "" {
		ctx.JSONWriteError(xproto.ErrParam, c)
		return
	}
	var param xproto.RawData
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqSerialTransfer, &param, &resp, i.deviceID, session); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrFileTransfer 文件传输
func (Request) FileTransferHandler(c *gin.Context) {
	var param xproto.FileTransfer
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	if param.Action == xproto.ActUpload {
		f, err := os.Stat(param.FileName)
		if err != nil {
			ctx.JSONWriteError(err, c)
			return
		}
		param.FileSize = int(f.Size())
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqFileTransfer, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrFtpTransfer ftp文件传输
func (Request) FtpTransferHandler(c *gin.Context) {
	var param xproto.FtpTransfer
	i, err := checkParam(c, &param)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	var resp interface{}
	if err := xproto.SyncSend(xproto.ReqFtpTransfer, &param, &resp, i.deviceID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(resp, c)
}

// DvrCloseLink 关闭链路
func (Request) CloseLinkHandler(c *gin.Context) {
	i, err := checkParam(c, nil)
	if err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	sessionID := c.Query("session")
	if err := xproto.SyncSend(xproto.ReqClose, nil, nil, i.deviceID, sessionID); err != nil {
		ctx.JSONWriteError(err, c)
		return
	}
	ctx.JSONWriteData(nil, c)
}

func (o Request) Router(r *gin.RouterGroup) {
	r.POST("/liveStream", o.LiveStreamHandler)
	r.POST("/voice", o.VoiceHandler)
	r.POST("/playback", o.PlaybackHandler)
	r.POST("/query", o.QueryHandler)
	r.POST("/parameters", o.ParametersHandler)
	r.POST("/ftpTransfer", o.FtpTransferHandler)
	r.POST("/fileTransfer", o.FileTransferHandler)
	r.POST("/closeLink", o.CloseLinkHandler)
	r.POST("/control", o.ControlHandler)
	r.POST("/user", o.UserHandler)
	r.POST("/serial/transparent", o.SerialTransparentHandler)
	r.POST("/serial/transfer", o.SerialTransferHandler)
}
